
#ifndef __TCP_CLIENT_H
#define __TCP_CLIENT_H

#include <vector>
#include <apr.h>
#include <apr_file_io.h>
#include <apr_portable.h>
#include "../aprtools/APRBucketBrigade.h"
#include "../aprtools/APRFuture.h"
#include "netgeneral.h"

// Five seconds.
#define CLIENT_SOCKET_TIMEOUT 60000

/** A basic TCP client class. This is the base class for all types of
 * clients. The constructor connects and the destructor
 * disconnects. */
class TCPClient
{
   public:
      TCPClient(const char *ihostname, int iportno, apr_pool_t *imp);
      virtual ~TCPClient();
      apr_off_t sendBucketBrigade(APRBucketBrigade *aprbb);
      apr_off_t sendBuffer(const char *buf, apr_off_t buflen);
      APRFuture<apr_off_t> *sendBufferFuture(const char *buf, apr_off_t buflen);
      static void *sendBufferThread(apr_thread_t *tthread, void *args);
      std::vector<char> *receiveBuffer(apr_off_t len);
      APRFuture<std::vector<char> *> *receiveBufferFuture(apr_off_t len);
      static void *receiveBufferThread(apr_thread_t *tthread, void *args);
      std::vector<char> *sendreceiveBuffer(const char *buf, apr_off_t sendlen, apr_off_t recvlen);
      APRFuture<std::vector<char> *> *sendreceiveBufferFuture(const char *buf, apr_off_t sendlen, apr_off_t recvlen);
      static void *sendreceiveBufferThread(apr_thread_t *tthread, void *args);
      /** Is this a valid client (connected)?
       * 
       * @return One if valid, zero if invalid. */
      int isValid() { return isvalid; }
      void invalidate();
      /** Get the memory pool associated with this client.
       * 
       * @return The client memory pool. */
      apr_pool_t *getMemoryPool() { return mp; }
   protected:
      virtual functor getSendBufferThread() const { return (functor)(&sendBufferThread); }
      virtual functor getReceiveBufferThread() const { return (functor)(&receiveBufferThread); }
      virtual functor getSendReceiveBufferThread() const { return (functor)(&sendreceiveBufferThread); }
      /** Is this a valid socket. */
      int isvalid;
      /** Pipe to the socket. */
      APRBucketBrigade *clientbb;
      /** Pointer to the open outgoing socket. */
      apr_socket_t *tsocket;
      /** Pointer to the socket address information of the
       * endpoint. */
      apr_sockaddr_t *addrstruct;
      /** Memory pool for use for allocating bits and pieces. */
      apr_pool_t *mp;
};

#endif
